﻿using System;
using System.Data;
using NUnit.Framework;

namespace NaturalKeySpike {
    [TestFixture]
    public class When_reusing_temp_table {
        private INhibernateUnitOfWork _uow;

        [SetUp]
        public void Before_each_test() {
            CommitAndResetUow();
        }

        [TestFixtureTearDown]
        public void After_all_tests() {
            _uow.Commit();
            _uow.Dispose();
        }

        [Test]
        public void Can_access_temp_table_within_same_unit_of_work() {
            CreateTempTable("#tmp");
            AssertTempTableCount("#tmp", 0);
        }

        [Test, ExpectedException(ExpectedMessage = "Invalid object name '#tmp2'.")]
        public void Cannot_access_temp_table_between_units_of_work() {
            CreateTempTable("#tmp2");
            CommitAndResetUow();
            AssertTempTableCount("#tmp2", 0);
        }

        private void CreateTempTable(string tableName) {
            using (var cmd = CreateCommand()) {
                cmd.CommandText = "create table " + tableName + " (Id int not null identity primary key);";
                cmd.ExecuteNonQuery();
            }
        }

        private void AssertTempTableCount(string tableName, int expectedCount) {
            using (var cmd = CreateCommand()) {
                cmd.CommandText = "select count(*) from " + tableName + ";";
                Assert.AreEqual(expectedCount, (int)cmd.ExecuteScalar());
            }
        }

        private IDbCommand CreateCommand() {
            var cmd = _uow.CurrentSession.Connection.CreateCommand();
            _uow.CurrentSession.Transaction.Enlist(cmd);
            return cmd;
        }

        private void CommitAndResetUow() {
            if (_uow != null) {
                _uow.Commit();
                _uow.Dispose();
            }

            _uow = new NhibernateUnitOfWork();
        }
    }
}
